<style lang="scss">
    .ui-display{
        .edit-cell{
            &:hover{
                /*cursor:url('https://alligator.io/images/chef-cur.svg'), move;*/
                /*cursor:url('/static/edit.svg') 6 12, auto;*/
                /*cursor:pointer;*/
                text-decoration:underline;
                color:rgba(#000, .5);
            }
        }
        .isEdit::before{
            content:'';
            display:inline-block;
            position:absolute;
            top:0;
            left:0;
            width:0;
            height:0;
            border-top:6px solid red;
            border-right:6px solid transparent;
        }
    }
    .edit-cell{
        display:inline-block;
    }
</style>
<template>
    <div class="pos-r ui-display ">
        <ui-display ref="ui-display"
            @click.native.stop
            class="pos-a"
            :style="popupPosition"
            v-if="showMe && comp && code"
            :code="code"
            :comp="comp"></ui-display>
        <slot></slot>
    </div>
</template>
<script>
    export default {
        name: 'ui-cell-edit',
        props: {
            value: {
                type: [Array, Object]
            }
        },
        computed: {
            // 1 v-modle 的语法糖实现
            _tableData: {
                get() {
                    return this.value;
                },
                set(val) {
                    this.$emit('input', val);
                }
            }
        },
        data() {
            return {
                code: null,
                comp: null,
                index: null,
                key: null,
                popupPosition: null,
                showMe: false,
                idNum: null,
                cellId: null,
                keyboardFn: null,
                cacheData: null,
                cellMarkEidt: false
            }
        },
        mounted() {

            // 第一次表格数据来了缓存一个
            if (this.value) {
                this.cacheData = JSON.parse(JSON.stringify(this.value));
            }

            // 通过单元格组件传递过来的参数修改表格数据
            this.$on('global:CELL_EDIT_TABLE', val => {
                // 2 v-modle 的语法糖实现
                this._tableData[this.index][this.key] = val

                // 告诉父级表格是否被编辑
                this.cellMarkEidt = (this.cacheData[this.index][this.key] !== this._tableData[this.index][this.key])
                this.$emit('update:is-edit', val)
            })

            // 单元格组件关闭后执行回调
            this.$on('global:CELL_EDIT_TABLE_BYE', val => {
                if (val) {
                    // callback
                }
            })

            // 监听键盘事件
            this.keyboard()

            // 添加按index排序的ID
            this.$nextTick(() => {
                this.$el.querySelectorAll('.edit-cell').forEach((el, idx) => {
                    el.id = 'cell-' + idx
                })

            })

            // 超出input范围点击后关闭编辑
            $('body').on('click', (e, trigger) => {
                //如果是jq的trigger触发就不执行关闭
                if (!trigger) {
                    this.clean()
                }
            })

            // 单元格点击后弹出编辑的方法，传递到父级
            this.$emit('update:open', this.openComp)
        },
        methods: {
            // 组件装载
            getComp(comp) {
                comp().then((module) => {
                    this.code = module.default
                    // 当组件加载完成后显示组件
                    if (this.comp) {
                        this.showMe = true
                    }
                })
            },
            // 定位组件
            positioning(el) {
                // 根据父级tebale定位弹出的编辑框
                let cellEditeTable
                let cellEditeTableDOMRect
                cellEditeTable = this.$el.querySelector('.el-table')
                cellEditeTableDOMRect = cellEditeTable.getBoundingClientRect()
                // console.log(cellEditeTableDOMRect)
                let reactObj = el.parentNode.getBoundingClientRect()
                // console.log(el, reactObj)
                // console.log(reactObj.top - cellEditeTableDOMRect.top)
                this.popupPosition = {
                    left: reactObj.left - cellEditeTableDOMRect.left + 2 + 'px',
                    top: reactObj.top - cellEditeTableDOMRect.top - 4 + 'px',
                    width: reactObj.width - 4 + 'px',
                    height: reactObj.height + 'px',
                    zIndex: '1'
                }

                // 设置ID
                this.idNum = (+el.id.split('-')[1] + 1)
                this.cellId = 'cell-' + this.idNum

            },
            // 键盘监听
            keyboard() {
                // 为了让tab键保持在文档范围的变态方式
                if (!$('#keepTabInDom')[0]) {
                    $(this.$el).prepend(`<input style="position: absolute; top: 0;left: 0; border:none"  id="keepTabInDom" type="text">`)
                }

                // 键盘快捷操作
                this.keyboardFn = (e) => {
                    // 按 esc键
                    if (e.key === 'Escape') {
                        this.showMe = false
                    }

                    // 按 Tab键
                    if (e.key === 'Tab') {
                        $('#keepTabInDom')[0].focus() // 为了让tab键保持在文档范围的变态方式
                        $('#' + this.cellId).trigger('click', ['trigger'])
                    }

                    // 按回车键
                    if (e.key === 'Enter') {
                        $('#' + this.cellId).trigger('click', ['trigger'])
                    }
                }
                // 绑定键盘事件事件
                window.addEventListener('keydown', this.keyboardFn)
            },
            // 点击显示组件
            openComp() {
                // 前先清理上一次的内容
                this.clean()

                this.$nextTick(() => {
                    // 对传入参数进行对应处理
                    let argArr = [...arguments]
                    let compName
                    argArr.map((param) => {
                        // 如果是 scope
                        if (typeof param === 'object' && param.row) {
                            this.index = param.$index
                            this.key = param.column.property
                            this.comp = {
                                vm: this,
                                data: param.row[this.key],
                                index: param.$index
                            }
                        }
                        // 如果是$event
                        if (typeof param === 'object' && param.target) {
                            this.positioning(param.target)
                        }
                        // 如果是需要打开的组件名称
                        if (typeof param === 'string') {
                            compName = param
                        }
                    })

                    // 动态加载组件
                    switch(compName){
                        case 'el-input':
                            this.getComp(() => import('./_comps/el-input.js'))
                            break;
                        case 'dropdown-tree':
                            this.getComp(() => import('./_comps/dropdown-tree.js'))
                            break;
                    }
                })

            },
            markEdit() {
                if (this.idNum) {
                    let el = $('#cell-' + (this.idNum - 1))
                    if (this.cellMarkEidt) {
                        el.addClass('isEdit')
                    }else{
                        el.removeClass('isEdit')
                    }

                }
            },
            // 清理组件
            clean() {
                this.showMe = false
                this.code = null
                this.comp = null
                this.markEdit()
            }
        },
        destroyed() {
            // 销毁键盘监听
            window.removeEventListener('keydown', this.keyboardFn)
            // 清理组件
            this.clean()
        }

    };
</script>

